package com.example.extension.framework;

import java.util.function.Consumer;
import java.util.function.Function;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 
 * @author jie.deng
 */
@Component
public class ExtensionExecutor {

    @Autowired
    private ExtensionRegister extensionRegister;
    @Autowired
    private ScenarioCapable scenarioCapable;

    /**
     * 根据注解信息选择实现类，执行指定方法(无返回值)
     * 
     * @param <T>
     * @param targetClz 接口Class对象
     * @param scenarioCode 接口编号
     * @param consumer
     */
    public <T> void executeVoid(Class<T> targetClz, String scenarioCode, Consumer<T> consumer) {
        T component = extensionRegister.locateComponent(targetClz, scenarioCode);
        if (null != component) {
            consumer.accept(component);
        }
    }

    /**
     * 根据注解信息选择实现类，执行指定方法(有返回值)
     * 
     * @param <R>
     * @param <T>
     * @param targetClz 接口Class对象
     * @param scenarioCode 接口编号
     * @param func
     * @return
     */
    public <R, T> R execute(Class<T> targetClz, String scenarioCode, Function<T, R> func) {
        T component = extensionRegister.locateComponent(targetClz, scenarioCode);
        if (null != component) {
            return func.apply(component);
        }
        return null;
    }

    
    /**
     * 根据租户配置+注解信息选择实现类，执行指定方法(无返回值)
     * 
     * @param <T>
     * @param targetClz
     * @param tenantCode
     * @param consumer
     */
    public <T> void executeVoidByTenantCode(Class<T> targetClz, String tenantCode, Consumer<T> consumer) {
        String scenarioCode = scenarioCapable.getScenarioCode(tenantCode, targetClz);
        executeVoid(targetClz, scenarioCode, consumer);
    }

    /**
     * 根据租户配置+注解信息选择实现类，执行指定方法(有返回值)
     * 
     * @param <R>
     * @param <T>
     * @param targetClz
     * @param tenantCode
     * @param func
     * @return
     */
    public <R, T> R executeByTenantCode(Class<T> targetClz, String tenantCode, Function<T, R> func) {
        String scenarioCode = scenarioCapable.getScenarioCode(tenantCode, targetClz);
        return execute(targetClz, scenarioCode, func);
    }

}
